<template>
  <div>
    <!-- 实名认证组件的结构 -->
    <el-card class="box-card">
      <!-- 卡片的头部 -->
      <template #header>
        <div class="card-header">
          <h1>实名信息</h1>
        </div>
      </template>
      <!-- 实名认证结构的提示部分 -->
      <div class="tip" style="color: #7f7f7f">
        <p>
          <el-icon>
            <InfoFilled />
          </el-icon>
          完成实名认证后才能添加就诊人，正常进行挂号，为了不影响后续步骤，建议提前实名认证。
        </p>
      </div>
      <!-- 卡片身体的底部：认证成功的结构，认证未成功的结构 -->
      <!-- 左侧展示订单详情信息 -->
      <el-descriptions
        v-if="userInfo.authStatus == 1"
        class="margin-top"
        :column="1"
        border
        style="margin: 20px auto"
      >
        <el-descriptions-item label-align="center" width="50px">
          <template #label>
            <div class="cell-item">用户姓名</div>
          </template>
          {{ userInfo.name }}
        </el-descriptions-item>
        <el-descriptions-item label-align="center" width="50px">
          <template #label>
            <div class="cell-item">证件类型</div>
          </template>
          {{ userInfo.certificatesType == '10' ? '身份证' : '户口本' }}
        </el-descriptions-item>
        <el-descriptions-item label-align="center" width="50px">
          <template #label>
            <div class="cell-item">证件号码</div>
          </template>
          {{ userInfo.certificatesNo }}
        </el-descriptions-item>
      </el-descriptions>
      <!-- 用户未验证的结构 -->
      <el-form
        v-if="userInfo.authStatus == 0"
        style="width: 60%; margin: 20px auto"
        label-width="80"
        :model="params"
        :rules="rules"
        ref="form"
      >
        <el-form-item label="用户姓名" prop="name">
          <el-input placeholder="请输入用户姓名" v-model="params.name"></el-input>
        </el-form-item>
        <el-form-item label="证件类型" prop="certificatesType">
          <el-select
            style="width: 100%"
            placeholder="请选择证件类型"
            v-model="params.certificatesType"
          >
            <el-option
              :label="item.name"
              :value="item.value"
              v-for="(item, index) in arrType"
              :key="index"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="证件号码" prop="certificatesNo">
          <el-input placeholder="请输入证件号码" v-model="params.certificatesNo"></el-input>
        </el-form-item>
        <el-form-item label="上传证件" prop="certificatesUrl">
          <!-- 
                        action: upload 组件向服务器提交图片的路径 
                        limit: 照片墙允许上传文件的最大数量
                        on-exceed: 超出约束数量的钩子
                    -->
          <el-upload
            ref="upload"
            list-type="picture-card"
            :on-preview="handlePictureCardPreView"
            :on-remove="handleRemove"
            action="/api/oss/file/fileUpload?fileHost=userAuah"
            limit="1"
            :on-exceed="exceedHandler"
            :on-success="successHandler"
          >
            <img
              style="width: 100%; height: 100%"
              src="../../../assets/images/auth_example.png"
              alt=""
            />
          </el-upload>

          <el-dialog v-model="dialogVisible">
            <img
              w-full
              v-if="params.certificatesUrl"
              style="width: 100%; height: 100%"
              :src="params.certificatesUrl"
              alt="Priview Image"
            />
          </el-dialog>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" size="default" @click="submit">提交</el-button>
          <el-button type="primary" size="default" @click="reset">重写</el-button>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script setup lang="ts">
//引入 elment-plus 图标
import { InfoFilled } from '@element-plus/icons-vue'

//获取用户信息
import { reqUserInfo, reqCertationType, reqUserCertation } from '@/api/user'
import type {
  UserInfoResponseData,
  CertificatesTypeResponseData,
  CertificatesArr,
  UserParams
} from '@/api/user/type'
//引入组合式 API 函数
import { onMounted, ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'
//获取 form 组件
let form = ref()
//存储用户信息
let userInfo: any = ref<any>({})
let arrType = ref<CertificatesArr>([])
//控制对话框的显示与隐藏
let dialogVisible = ref<boolean>(false)
//收集用户表单认证的数据
let params = reactive<UserParams>({
  certificatesNo: '',
  certificatesType: '',
  certificatesUrl: '',
  name: ''
})
let upload = ref()

//组件挂载完毕
onMounted(() => {
  ////获取用户信息
  getUserInfo()
  //获取证件类型的接口
  getType()
})

//获取用户信息的方法
const getUserInfo = async () => {
  let result: UserInfoResponseData = await reqUserInfo()
  if (result.code == 200) {
    userInfo.value = result.data
  }
}

//获取证件类型的接口
const getType = async () => {
  let result: CertificatesTypeResponseData = await reqCertationType()
  if (result.code == 200) {
    arrType.value = result.data
  }
}

//超出数量的钩子
const exceedHandler = () => {
  ElMessage({
    type: 'error',
    message: '图片只能上传一张'
  })
}

//@ts-ignore
//图片上传成功的钩子
const successHandler = (response: any) => {
  //如果图片上传成功，清除校验的结果
  form.value.clearValidate('certificatesUrl')
  //收集上传成功的图片的地址
  //response: 上传图片成功服务器返回的数据
  //uploadFile: 上传文件对象
  //uploadFiles: 上传图片所有对象的集合
  params.certificatesUrl = response.data
}

//照片墙预览的钩子
const handlePictureCardPreView = () => {
  //触发预览钩子的时候，对话框显示
  dialogVisible.value = true
}

//照片墙删除的钩子
const handleRemove = () => {
  params.certificatesUrl = ''
}

//重写按钮的回调
const reset = () => {
  //清空上传组件文件列表
  upload.value.clearFiles()
  //清空数据
  Object.assign(params, {
    certificatesNo: '',
    certificatesType: '',
    certificatesUrl: '',
    name: ''
  })
}
//提交按钮的回调
const submit = async () => {
  //全部的表单校验通过，返回一个成功的 Promise
  //如果有一个表单校验失败，返回一个失败的 Promise，后面的语句不再执行
  await form.value.validate()

  try {
    //认证成功
    await reqUserCertation(params)
    //提示消息
    ElMessage({
      type: 'success',
      message: '认证成功'
    })
    //认证成功之后重新获取用户信息
    getUserInfo()
  } catch (error) {
    ElMessage({
      type: 'error',
      message: '认证失败'
    })
  }
}

//自定义校验规则姓名的方法
//rule: 当前校验字段的规则对象
//value: 要校验表单元素的文本内容
//callBack: 是否通过校验
//@ts-ignore

const validatorName = (rule: any, value: any, callBack: any) => {
  var reg =
    /^[\u00B7\u3007\u3400-\u4DBF\u4E00-\u9FFF\uE000-\uF8FF\uD840-\uD8C0\uDC00-\uDFFF\uF900-\uFAFF]+$/u
  if (reg.test(value)) {
    callBack()
  } else {
    callBack(new Error('请输入正确的中国人的名字'))
  }
}

//证件类型校验的方法
//@ts-ignore
const validatorType = (rule: any, value: any, callBack: any) => {
  if (value == '10' || value == '20') {
    callBack()
  } else {
    callBack(new Error('请选择证件类型'))
  }
}

//证件号码校验的方法
//@ts-ignore
const validatorNo = (rule: any, value: any, callBack: any) => {
  var sfz = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
  let hkb = /^\d{9}$/
  if (sfz.test(value) || hkb.test(value)) {
    callBack()
  } else {
    callBack(new Error('请输入正确的证件号码'))
  }
}

//证件照图片校验的方法
//@ts-ignore
const validatorUrl = (rule: any, value: any, callBack: any) => {
  if (value.length) {
    callBack()
  } else {
    callBack(new Error('请上传证件照图片'))
  }
}

//表单校验的规则对象
const rules = {
  //用户姓名的校验规则
  //required=true:代表当前字段必须校验
  name: [
    {
      required: true,
      validator: validatorName
    }
  ],
  certificatesType: [
    {
      required: true,
      validator: validatorType
    }
  ],
  certificatesNo: [
    {
      required: true,
      validator: validatorNo
    }
  ],
  certificatesUrl: [
    {
      required: true,
      validator: validatorUrl
    }
  ]
}
</script>

<style scoped lang="scss">
.box-card {
  .tip {
    display: flex;
    justify-content: center;
    align-items: center;
  }
}
</style>
